// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: linchuan

#include "coin2/exchange/bithumb/api_order/native_rest_async_asio_subscriber.h"

#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>

#include "coin2/base/log.h"
#include "coin2/exchange/bithumb/api_util/order_manager.h"

namespace coin2::exchange::bithumb::api_order {

void BithumbRestAsyncAsioSubscriber::QueryBalance() {
  RestParams params;
  params.set_currency("ALL");
  auto http_context = rest_client()->QueryBalance(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&BithumbRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void BithumbRestAsyncAsioSubscriber::QueryOpenOrders(
    const std::pair<std::string, std::string>& ccy) {
  RestParams params;
  params.set_order_currency(ccy.first);
  params.set_payment_currency(ccy.second);
  params.set_count("100");
  auto http_context = rest_client()->QueryOpenOrders(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&BithumbRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void BithumbRestAsyncAsioSubscriber::QueryFills(const std::pair<std::string, std::string>& ccy) {
  RestParams params;
  params.set_order_currency(ccy.first);
  params.set_payment_currency(ccy.second);
  params.set_count("50");
  auto http_context = rest_client()->QueryTrades(params);
  if (!http_context) {
    return;
  }
  http_context->handler =
      std::bind(&BithumbRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void BithumbRestAsyncAsioSubscriber::QueryFillsV2() {
  RestParams params;
  const auto open_orders = order_mgr_->GetOpenOrdersCopy();
  for (const auto& order_pair : open_orders) {
    const auto& order = order_pair.second;
    if (!order) {
      continue;
    }
    params.set_order_id(order->order_id);
    params.set_order_currency(order->currency);
    params.set_payment_currency(order->payment_currency);
    auto http_context = rest_client()->QueryTradesV2(params);
    if (!http_context) {
      continue;
    }
    http_context->handler =
        std::bind(&BithumbRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
    http_driver_->PostAsyncContext(http_context);
  }
}

void BithumbRestAsyncAsioSubscriber::SubscribeAsync() {
  AddPeriodicTask(
      std::bind(&BithumbRestAsyncAsioSubscriber::QueryBalance, this),
      config_.query_account_balance_period_sec(),
      "query_balance");

  const auto currency_list = GetCurrencies();
  AddPeriodicTask(
      std::bind(&BithumbRestAsyncAsioSubscriber::QueryOpenOrders, this, std::placeholders::_1),
      config_.query_open_orders_period_sec(),
      "query_open_orders",
      currency_list);
  if (coin2::exchange::bithumb::api_util::RateLimitPreventMode()) {
    AddPeriodicTask(
        std::bind(&BithumbRestAsyncAsioSubscriber::QueryFills, this, std::placeholders::_1),
        config_.query_fill_period_sec(),
        "query_fills",
        currency_list);
  } else {
    AddPeriodicTask(
        std::bind(&BithumbRestAsyncAsioSubscriber::QueryFillsV2, this),
        config_.query_fill_period_sec(),
        "query_fills");
  }
}

}  // namespace coin2::exchange::bithumb::api_order
